using GroupSix.Application.Dtos;
using GroupSix.Domain.Repositories;
using GroupSix.Domain.Entity.App;
using GroupSix.Domain.common;
using Microsoft.Extensions.Logging;
using System.Text.Json;

namespace GroupSix.Application.Services;

/// <summary>
/// 系统设置服务
/// </summary>
public class SystemSettingService
{
    private readonly ISystemSettingRepository _systemSettingRepository;
    private readonly ISystemSettingLogRepository _systemSettingLogRepository;
    private readonly ILogger<SystemSettingService> _logger;

    public SystemSettingService(
        ISystemSettingRepository systemSettingRepository,
        ISystemSettingLogRepository systemSettingLogRepository,
        ILogger<SystemSettingService> logger)
    {
        _systemSettingRepository = systemSettingRepository;
        _systemSettingLogRepository = systemSettingLogRepository;
        _logger = logger;
    }

    /// <summary>
    /// 获取系统设置列表
    /// </summary>
    /// <param name="query">查询条件</param>
    /// <returns>分页结果</returns>
    public async Task<PageResult<SystemSettingDto>> GetSystemSettingsAsync(SystemSettingQueryDto query)
    {
        try
        {
            var pageRequest = new PageRequest
            {
                PageIndex = query.Page,
                PageSize = query.PageSize
            };

            var result = await _systemSettingRepository.GetPagedAsync(pageRequest);
            
            var dtos = result.Items.Select(MapToDto).ToList();
            
            return new PageResult<SystemSettingDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取系统设置列表失败");
            throw;
        }
    }

    /// <summary>
    /// 根据键获取系统设置
    /// </summary>
    /// <param name="settingKey">设置键</param>
    /// <returns>系统设置</returns>
    public async Task<SystemSettingDto?> GetSystemSettingByKeyAsync(string settingKey)
    {
        try
        {
            var setting = await _systemSettingRepository.GetByKeyAsync(settingKey);
            return setting != null ? MapToDto(setting) : null;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据键获取系统设置失败: {SettingKey}", settingKey);
            throw;
        }
    }

    /// <summary>
    /// 根据分组获取系统设置
    /// </summary>
    /// <param name="group">分组</param>
    /// <returns>设置列表</returns>
    public async Task<List<SystemSettingDto>> GetSystemSettingsByGroupAsync(string group)
    {
        try
        {
            var settings = await _systemSettingRepository.GetByGroupAsync(group);
            return settings.Select(MapToDto).ToList();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "根据分组获取系统设置失败: {Group}", group);
            throw;
        }
    }

    /// <summary>
    /// 创建系统设置
    /// </summary>
    /// <param name="request">创建请求</param>
    /// <param name="operatorId">操作人ID</param>
    /// <param name="operatorName">操作人姓名</param>
    /// <returns>创建结果</returns>
    public async Task<bool> CreateSystemSettingAsync(CreateSystemSettingRequestDto request, Guid operatorId, string operatorName)
    {
        try
        {
            // 检查设置键是否已存在
            if (await _systemSettingRepository.ExistsByKeyAsync(request.SettingKey))
            {
                throw new InvalidOperationException($"设置键 '{request.SettingKey}' 已存在");
            }

            var setting = new GsSystemSetting
            {
                Id = Guid.NewGuid(),
                SettingKey = request.SettingKey,
                SettingValue = request.SettingValue,
                Description = request.Description,
                SettingType = request.SettingType,
                IsSystemLevel = request.IsSystemLevel,
                Group = request.Group,
                SortOrder = request.SortOrder,
                IsReadOnly = request.IsReadOnly,
                CreatedBy = operatorId,
                UpdatedBy = operatorId,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            await _systemSettingRepository.CreateAsync(setting);

            // 记录创建日志
            await LogSettingChangeAsync(setting, null, setting.SettingValue, "创建系统设置", "create", operatorId, operatorName);

            _logger.LogInformation("系统设置创建成功: {SettingKey}", request.SettingKey);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "创建系统设置失败: {SettingKey}", request.SettingKey);
            throw;
        }
    }

    /// <summary>
    /// 更新系统设置
    /// </summary>
    /// <param name="id">设置ID</param>
    /// <param name="request">更新请求</param>
    /// <param name="operatorId">操作人ID</param>
    /// <param name="operatorName">操作人姓名</param>
    /// <returns>更新结果</returns>
    public async Task<bool> UpdateSystemSettingAsync(Guid id, UpdateSystemSettingRequestDto request, Guid operatorId, string operatorName)
    {
        try
        {
            var setting = await _systemSettingRepository.GetByIdAsync(id);
            if (setting == null)
            {
                throw new InvalidOperationException($"系统设置不存在: {id}");
            }

            // 检查是否为只读设置
            if (setting.IsReadOnly)
            {
                throw new InvalidOperationException($"设置 '{setting.SettingKey}' 为只读，无法修改");
            }

            var oldValue = setting.SettingValue;
            var oldDescription = setting.Description;

            // 更新设置
            setting.SettingValue = request.SettingValue;
            setting.Description = request.Description;
            setting.UpdatedBy = operatorId;
            setting.UpdatedAt = DateTime.UtcNow;

            await _systemSettingRepository.UpdateAsync(setting);

            // 记录变更日志
            var changeReason = string.IsNullOrEmpty(request.ChangeReason) ? "更新系统设置" : request.ChangeReason;
            await LogSettingChangeAsync(setting, oldValue, setting.SettingValue, changeReason, "update", operatorId, operatorName);

            _logger.LogInformation("系统设置更新成功: {SettingKey}, 旧值: {OldValue}, 新值: {NewValue}", 
                setting.SettingKey, oldValue, setting.SettingValue);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "更新系统设置失败: {Id}", id);
            throw;
        }
    }

    /// <summary>
    /// 删除系统设置
    /// </summary>
    /// <param name="id">设置ID</param>
    /// <param name="operatorId">操作人ID</param>
    /// <param name="operatorName">操作人姓名</param>
    /// <returns>删除结果</returns>
    public async Task<bool> DeleteSystemSettingAsync(Guid id, Guid operatorId, string operatorName)
    {
        try
        {
            var setting = await _systemSettingRepository.GetByIdAsync(id);
            if (setting == null)
            {
                throw new InvalidOperationException($"系统设置不存在: {id}");
            }

            // 检查是否为系统级设置
            if (setting.IsSystemLevel)
            {
                throw new InvalidOperationException($"系统级设置 '{setting.SettingKey}' 无法删除");
            }

            await _systemSettingRepository.DeleteAsync(id);

            // 记录删除日志
            await LogSettingChangeAsync(setting, setting.SettingValue, "", "删除系统设置", "delete", operatorId, operatorName);

            _logger.LogInformation("系统设置删除成功: {SettingKey}", setting.SettingKey);
            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "删除系统设置失败: {Id}", id);
            throw;
        }
    }

    /// <summary>
    /// 获取设置变更日志
    /// </summary>
    /// <param name="settingKey">设置键</param>
    /// <param name="page">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <returns>日志列表</returns>
    public async Task<PageResult<SystemSettingLogDto>> GetSettingLogsAsync(string settingKey, int page = 1, int pageSize = 20)
    {
        try
        {
            var result = await _systemSettingLogRepository.GetLogsBySettingKeyAsync(settingKey, page, pageSize);
            
            var dtos = result.Items.Select(MapToLogDto).ToList();
            
            return new PageResult<SystemSettingLogDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取设置变更日志失败: {SettingKey}", settingKey);
            throw;
        }
    }

    /// <summary>
    /// 获取最近的设置变更日志
    /// </summary>
    /// <param name="page">页码</param>
    /// <param name="pageSize">页大小</param>
    /// <returns>日志列表</returns>
    public async Task<PageResult<SystemSettingLogDto>> GetRecentLogsAsync(int page = 1, int pageSize = 20)
    {
        try
        {
            var result = await _systemSettingLogRepository.GetRecentLogsAsync(page, pageSize);
            
            var dtos = result.Items.Select(MapToLogDto).ToList();
            
            return new PageResult<SystemSettingLogDto>
            {
                Items = dtos,
                TotalCount = result.TotalCount,
                PageIndex = result.PageIndex,
                PageSize = result.PageSize
            };
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "获取最近设置变更日志失败");
            throw;
        }
    }

    /// <summary>
    /// 记录设置变更日志
    /// </summary>
    private async Task LogSettingChangeAsync(GsSystemSetting setting, string? oldValue, string newValue, string changeReason, string operationType, Guid operatorId, string operatorName)
    {
        try
        {
            var log = new GsSystemSettingLog
            {
                Id = Guid.NewGuid(),
                SettingKey = setting.SettingKey,
                OldValue = oldValue ?? "",
                NewValue = newValue,
                ChangeReason = changeReason,
                OperationType = operationType,
                OperatorId = operatorId,
                OperatorName = operatorName,
                IpAddress = "", // 可以从HttpContext获取
                UserAgent = "", // 可以从HttpContext获取
                CreatedBy = operatorId,
                UpdatedBy = operatorId,
                CreatedAt = DateTime.UtcNow,
                UpdatedAt = DateTime.UtcNow
            };

            await _systemSettingLogRepository.CreateAsync(log);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "记录设置变更日志失败: {SettingKey}", setting.SettingKey);
        }
    }

    /// <summary>
    /// 映射到DTO
    /// </summary>
    private SystemSettingDto MapToDto(GsSystemSetting setting)
    {
        return new SystemSettingDto
        {
            Id = setting.Id,
            SettingKey = setting.SettingKey,
            SettingValue = setting.SettingValue,
            Description = setting.Description,
            SettingType = setting.SettingType,
            IsSystemLevel = setting.IsSystemLevel,
            Group = setting.Group,
            SortOrder = setting.SortOrder,
            IsReadOnly = setting.IsReadOnly,
            CreatedAt = setting.CreatedAt,
            UpdatedAt = setting.UpdatedAt
        };
    }

    /// <summary>
    /// 映射到日志DTO
    /// </summary>
    private SystemSettingLogDto MapToLogDto(GsSystemSettingLog log)
    {
        return new SystemSettingLogDto
        {
            Id = log.Id,
            SettingKey = log.SettingKey,
            OldValue = log.OldValue,
            NewValue = log.NewValue,
            ChangeReason = log.ChangeReason,
            OperationType = log.OperationType,
            OperatorName = log.OperatorName,
            IpAddress = log.IpAddress,
            CreatedAt = log.CreatedAt
        };
    }
} 